home *** CD-ROM | disk | FTP | other *** search
- /*
- * fsPdev.c --
- *
- * Copyright 1987, 1988 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /sprite/src/kernel/fspdev/RCS/fspdevControl.c,v 9.3 91/06/26 01:07:12 mottsmth Exp $ SPRITE (Berkeley)";
- #endif not lint
-
- #include <sprite.h>
- #include <fs.h>
- #include <fsconsist.h>
- #include <fsutil.h>
- #include <fspdev.h>
- #include <fspdevInt.h>
- #include <fsNameOps.h>
- #include <fsio.h>
- #include <fsioLock.h>
- #include <fsStat.h>
- #include <proc.h>
- #include <rpc.h>
-
- /*
- *----------------------------------------------------------------------------
- *
- * FspdevControlHandleInit --
- *
- * Fetch and initialize a control handle for a pseudo-device.
- *
- * Results:
- * A pointer to the control stream I/O handle. The found parameter is
- * set to TRUE if the handle was already found, FALSE if we created it.
- *
- * Side effects:
- * Initializes and installs the control handle.
- *
- *----------------------------------------------------------------------------
- *
- */
- Fspdev_ControlIOHandle *
- FspdevControlHandleInit(fileIDPtr, name)
- Fs_FileID *fileIDPtr;
- char *name;
- {
- register Boolean found;
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
- Fs_HandleHeader *hdrPtr;
-
- found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fspdev_ControlIOHandle), name,
- FALSE, &hdrPtr);
- ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
- if (!found) {
- ctrlHandlePtr->serverID = NIL;
- List_Init(&ctrlHandlePtr->queueHdr);
- ctrlHandlePtr->seed = 0;
- List_Init(&ctrlHandlePtr->readWaitList);
- Fsio_LockInit(&ctrlHandlePtr->lock);
- Fsutil_RecoveryInit(&ctrlHandlePtr->rmt.recovery);
- ctrlHandlePtr->accessTime = 0;
- ctrlHandlePtr->modifyTime = 0;
- ctrlHandlePtr->owner.id = (Proc_PID)NIL;
- ctrlHandlePtr->owner.procOrFamily = 0;
- ctrlHandlePtr->prefixPtr = (Fsprefix *)NIL;
- fs_Stats.object.controls++;
- }
- return(ctrlHandlePtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlIoOpen --
- *
- * Complete setup of the server's control stream. Called from
- * Fs_Open on the host running the server. We mark the Control
- * I/O handle as having a server (us).
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Installs the Control I/O handle and keeps a reference to it.
- * Marks the process as not suitable for migration.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevControlIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
- ioHandlePtrPtr)
- register Fs_FileID *ioFileIDPtr; /* I/O fileID */
- int *flagsPtr; /* FS_READ | FS_WRITE ... */
- int clientID; /* Host doing the open */
- ClientData streamData; /* NIL. */
- char *name; /* File name for error msgs */
- Fs_HandleHeader **ioHandlePtrPtr;/* Return - a locked handle set up for
- * I/O to a control stream, or NIL */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
-
- ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, name);
- if (!List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
- panic( "FsControlStreamCltOpen found control msgs\n");
- }
- ctrlHandlePtr->serverID = clientID;
- *ioHandlePtrPtr = (Fs_HandleHeader *)ctrlHandlePtr;
- /*
- * Can't migrate pseudo-device servers.
- */
- Proc_NeverMigrate(Proc_GetCurrentProc());
- Fsutil_HandleUnlock(ctrlHandlePtr);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlSelect --
- *
- * Select on the server's control stream. This returns readable
- * if there are control messages in the queue.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Puts the caller on the handle's read wait list if the control
- * stream isn't selectable.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- FspdevControlSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
- Fs_HandleHeader *hdrPtr; /* Handle on device to select */
- Sync_RemoteWaiter *waitPtr; /* Process info for remote waiting */
- int *readPtr; /* Bit to clear if non-readable */
- int *writePtr; /* Bit to clear if non-writeable */
- int *exceptPtr; /* Bit to clear if non-exceptable */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr =
- (Fspdev_ControlIOHandle *)hdrPtr;
-
- Fsutil_HandleLock(ctrlHandlePtr);
- if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
- if (waitPtr != (Sync_RemoteWaiter *)NIL) {
- Fsutil_FastWaitListInsert(&ctrlHandlePtr->readWaitList, waitPtr);
- }
- *readPtr = 0;
- }
- *writePtr = *exceptPtr = 0;
- Fsutil_HandleUnlock(ctrlHandlePtr);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlRead --
- *
- * Read from the server's control stream. The server learns of new
- * clients by reading this stream. Internally the stream is a list
- * of addresses of streams created for the server. This routine maps
- * those addresses to streamIDs for the user level server process and
- * returns them to the reader.
- *
- * Results:
- * SUCCESS, FS_WOULD_BLOCK,
- * or an error code from setting up a new stream ID.
- *
- * Side effects:
- * The server's list of stream ptrs in the process table is updated.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- FspdevControlRead(streamPtr, readPtr, waitPtr, replyPtr)
- Fs_Stream *streamPtr; /* Control stream */
- Fs_IOParam *readPtr; /* Read parameter block. */
- Sync_RemoteWaiter *waitPtr; /* Process info for remote waiting */
- Fs_IOReply *replyPtr; /* Signal to return, if any,
- * plus the amount read. */
- {
- ReturnStatus status;
- register Fspdev_ControlIOHandle *ctrlHandlePtr =
- (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
- Pdev_Notify notify; /* Message returned to
- * user-level server proc */
-
- Fsutil_HandleLock(ctrlHandlePtr);
-
- if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
- /*
- * No control messages ready.
- */
- Fsutil_FastWaitListInsert(&ctrlHandlePtr->readWaitList, waitPtr);
- replyPtr->length = 0;
- status = FS_WOULD_BLOCK;
- } else {
- register FspdevNotify *notifyPtr; /* Internal message */
- notifyPtr = (FspdevNotify *)List_First(&ctrlHandlePtr->queueHdr);
- List_Remove((List_Links *)notifyPtr);
- notify.magic = PDEV_NOTIFY_MAGIC;
- status = Fs_GetStreamID(notifyPtr->streamPtr, ¬ify.newStreamID);
- if (status != SUCCESS) {
- replyPtr->length = 0;
- } else {
- if (readPtr->flags & FS_USER) {
- status = Vm_CopyOut(sizeof(notify), (Address) ¬ify,
- readPtr->buffer);
- /*
- * No need to close on error because the stream is already
- * installed in the server process's state. It'll be
- * closed automatically when the server exits.
- */
- } else {
- bcopy((Address)¬ify, readPtr->buffer, sizeof(notify));
- }
- replyPtr->length = sizeof(notify);
- }
- free((Address)notifyPtr);
- }
- Fsutil_HandleUnlock(ctrlHandlePtr);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlIOControl --
- *
- * IOControls for the control stream.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * Command dependent.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- FspdevControlIOControl(streamPtr, ioctlPtr, replyPtr)
- Fs_Stream *streamPtr; /* I/O handle */
- Fs_IOCParam *ioctlPtr; /* I/O Control parameter block */
- Fs_IOReply *replyPtr; /* Return length and signal */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr =
- (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
- register ReturnStatus status;
-
- if (ioctlPtr->format != mach_Format) {
- panic("FsControlIOControl: wrong format\n");
- }
- switch(ioctlPtr->command) {
- case IOC_PDEV_SIGNAL_OWNER:
- status = FspdevSignalOwner(ctrlHandlePtr, ioctlPtr);
- break;
- case IOC_REPOSITION:
- status = SUCCESS;
- break;
- case IOC_GET_FLAGS:
- if (ioctlPtr->outBufSize >= sizeof(int)) {
- *(int *)ioctlPtr->outBuffer = 0;
- replyPtr->length = sizeof(int); /* to quiet lint */
- }
- status = SUCCESS;
- break;
- case IOC_SET_FLAGS:
- case IOC_SET_BITS:
- case IOC_CLEAR_BITS:
- status = SUCCESS;
- break;
- case IOC_TRUNCATE:
- status = SUCCESS;
- break;
- case IOC_LOCK:
- case IOC_UNLOCK:
- Fsutil_HandleLock(ctrlHandlePtr);
- status = Fsio_IocLock(&ctrlHandlePtr->lock, ioctlPtr,
- &streamPtr->hdr.fileID);
- Fsutil_HandleUnlock(ctrlHandlePtr);
- break;
- case IOC_NUM_READABLE: {
- register int bytesAvailable;
-
- if (ioctlPtr->outBufSize < sizeof(int)) {
- return(GEN_INVALID_ARG);
- }
- Fsutil_HandleLock(ctrlHandlePtr);
- if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
- bytesAvailable = 0;
- } else {
- bytesAvailable = sizeof(Pdev_Notify);
- }
- Fsutil_HandleUnlock(ctrlHandlePtr);
- status = SUCCESS;
- *(int *)ioctlPtr->outBuffer = bytesAvailable;
- break;
- }
- case IOC_SET_OWNER:
- case IOC_GET_OWNER:
- case IOC_MAP:
- status = GEN_NOT_IMPLEMENTED;
- break;
- case IOC_PREFIX:
- status = SUCCESS;
- break;
- default:
- status = GEN_INVALID_ARG;
- break;
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlGetIOAttr --
- *
- * Called from Fs_GetAttrStream to get the I/O attributes of a
- * pseudo-device. The access and modify times of the pseudo-device
- * are obtained from the internal pdev state.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- FspdevControlGetIOAttr(fileIDPtr, clientID, attrPtr)
- register Fs_FileID *fileIDPtr; /* Identfies pdev connection */
- int clientID; /* Host ID of process asking
- * for the attributes */
- register Fs_Attributes *attrPtr; /* Return - the attributes */
- {
- Fspdev_ControlIOHandle *ctrlHandlePtr;
-
- ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
- if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
- printf( "FspdevControlGetIOAttr, no %s handle <%d,%x,%x> client %d\n",
- Fsutil_FileTypeToString(fileIDPtr->type), fileIDPtr->serverID,
- fileIDPtr->major, fileIDPtr->minor, clientID);
- return(FS_FILE_NOT_FOUND);
- }
-
- if (ctrlHandlePtr->accessTime > 0) {
- attrPtr->accessTime.seconds = ctrlHandlePtr->accessTime;
- }
- if (ctrlHandlePtr->modifyTime > 0) {
- attrPtr->dataModifyTime.seconds = ctrlHandlePtr->modifyTime;
- }
-
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlSetIOAttr --
- *
- * Set the IO attributes of a pseudo-device.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * Updates the access and modify times kept in the pdev state.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- FspdevControlSetIOAttr(fileIDPtr, attrPtr, flags)
- register Fs_FileID *fileIDPtr; /* Identfies pdev connection */
- register Fs_Attributes *attrPtr; /* Return - the attributes */
- int flags; /* Tells which attrs to set */
- {
- Fspdev_ControlIOHandle *ctrlHandlePtr;
-
- ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
- if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
- printf( "FspdevControlSetIOAttr, no handle <%d,%d,%x,%x>\n",
- fileIDPtr->serverID, fileIDPtr->type,
- fileIDPtr->major, fileIDPtr->minor);
- return(FS_FILE_NOT_FOUND);
- }
- if (flags & FS_SET_TIMES) {
- ctrlHandlePtr->accessTime = attrPtr->accessTime.seconds;
- ctrlHandlePtr->modifyTime = attrPtr->dataModifyTime.seconds;
- }
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlVerify --
- *
- * This is called during recovery.
- * When the server at a remote site reopens its control stream it
- * contacts the file server to re-establish itself as the server.
- * This procedure is called from Fsio_StreamReopen to get the control
- * handle associated with the top-level shadow stream here at the
- * file server.
- *
- * Results:
- * A pointer to the control I/O handle, or NIL if the server is bad.
- *
- * Side effects:
- * The handle is returned locked and with its refCount incremented.
- * It should be released with Fsutil_HandleRelease.
- *
- *----------------------------------------------------------------------
- */
-
- Fs_HandleHeader *
- FspdevControlVerify(fileIDPtr, pdevServerHostID, domainTypePtr)
- Fs_FileID *fileIDPtr; /* control I/O file ID */
- int pdevServerHostID; /* Host ID of the client */
- int *domainTypePtr; /* Return - FS_PSEUDO_DOMAIN */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
- int serverID = -1;
-
- ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
- if (ctrlHandlePtr != (Fspdev_ControlIOHandle *)NIL) {
- if (ctrlHandlePtr->serverID != pdevServerHostID) {
- serverID = ctrlHandlePtr->serverID;
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- ctrlHandlePtr = (Fspdev_ControlIOHandle *)NIL;
- }
- }
- if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
- printf("FspdevControlVerify, server mismatch (%d not %d) for %s <%x,%x>\n",
- pdevServerHostID, serverID, Fsutil_FileTypeToString(fileIDPtr->type),
- fileIDPtr->major, fileIDPtr->minor);
- }
- if (domainTypePtr != (int *)NIL) {
- *domainTypePtr = FS_PSEUDO_DOMAIN;
- }
- return((Fs_HandleHeader *)ctrlHandlePtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlReopen --
- *
- * Reopen a control stream. A control handle is kept on both the
- * file server as well as the pseudo-device server's host. If the
- * file server reboots a reopen has to be done in order to set
- * the serverID field on the file server so subsequent client opens work.
- * Thus this is called on a remote client to contact the file server,
- * and then on the file server from the RPC stub.
- *
- * Results:
- * SUCCESS if there is no conflict with the server reopening.
- *
- * Side effects:
- * On the file server the serverID field is set.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- FspdevControlReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
- Fs_HandleHeader *hdrPtr;
- int clientID; /* ID of pdev server's host */
- ClientData inData; /* FspdevControlReopenParams */
- int *outSizePtr; /* IGNORED */
- ClientData *outDataPtr; /* IGNORED */
-
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr;
- register FspdevControlReopenParams *reopenParamsPtr;
- register ReturnStatus status = SUCCESS;
-
- if (hdrPtr != (Fs_HandleHeader *)NIL) {
- /*
- * Called on the pdev server's host to contact the remote
- * file server and re-establish state.
- */
- Fspdev_ControlIOHandle *ctrlHandlePtr;
- FspdevControlReopenParams params;
- int outSize = 0;
-
- ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
- reopenParamsPtr = ¶ms;
- reopenParamsPtr->fileID = hdrPtr->fileID;
- reopenParamsPtr->serverID = ctrlHandlePtr->serverID;
- reopenParamsPtr->seed = ctrlHandlePtr->seed;
- status = FsrmtReopen(hdrPtr, sizeof(FspdevControlReopenParams),
- (Address)reopenParamsPtr, &outSize, (Address)NIL);
- } else {
- /*
- * Called on the file server to re-establish a control handle
- * that corresponds to a control handle on the pdev server's host.
- */
-
- reopenParamsPtr = (FspdevControlReopenParams *)inData;
- ctrlHandlePtr = FspdevControlHandleInit(&reopenParamsPtr->fileID,
- (char *)NIL);
- if (reopenParamsPtr->serverID != NIL) {
- /*
- * The remote host thinks it is running the pdev server process.
- */
- if (ctrlHandlePtr->serverID == NIL) {
- ctrlHandlePtr->serverID = reopenParamsPtr->serverID;
- ctrlHandlePtr->seed = reopenParamsPtr->seed;
- } else if (ctrlHandlePtr->serverID != clientID) {
- printf(
- "PdevControlReopen conflict, %d lost to %d, %s <%x,%x>\n",
- clientID, ctrlHandlePtr->serverID,
- Fsutil_FileTypeToString(ctrlHandlePtr->rmt.hdr.fileID.type),
- ctrlHandlePtr->rmt.hdr.fileID.major,
- ctrlHandlePtr->rmt.hdr.fileID.minor);
- status = FS_FILE_BUSY;
- }
- } else if (ctrlHandlePtr->serverID == clientID) {
- /*
- * The pdev server closed while we were down or unable
- * to communicate.
- */
- ctrlHandlePtr->serverID = NIL;
- }
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlClose --
- *
- * Close a server process's control stream. After this the pseudo-device
- * is no longer active and client operations will fail.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * Reset the control handle's serverID.
- * Clears out the state for the control message queue.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- #ifdef SOSP91
- ReturnStatus
- FspdevControlClose(streamPtr, clientID, procID, flags, size, data, offsetPtr,
- rwFlagsPtr)
- #else
- ReturnStatus
- FspdevControlClose(streamPtr, clientID, procID, flags, size, data)
- #endif
- Fs_Stream *streamPtr; /* Control stream */
- int clientID; /* HostID of client closing */
- Proc_PID procID; /* ID of closing process */
- int flags; /* Flags from the stream being closed */
- int size; /* Should be zero */
- ClientData data; /* IGNORED */
- #ifdef SOSP91
- int *offsetPtr; /* Not used. */
- int *rwFlagsPtr; /* Not used. */
- #endif
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr =
- (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
- register FspdevNotify *notifyPtr;
- int extra = 0;
-
- /*
- * Close any server streams that haven't been given to
- * the master process yet.
- */
- while (!List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
- notifyPtr = (FspdevNotify *)List_First(&ctrlHandlePtr->queueHdr);
- List_Remove((List_Links *)notifyPtr);
- extra++;
- (void)Fs_Close(notifyPtr->streamPtr);
- free((Address)notifyPtr);
- }
- if (extra) {
- printf( "FspdevControlClose found %d left over messages\n",
- extra);
- }
- /*
- * Reset the pseudo-device server ID, both here and at the name server.
- */
- ctrlHandlePtr->serverID = NIL;
- if (ctrlHandlePtr->rmt.hdr.fileID.serverID != rpc_SpriteID) {
- (void)Fsrmt_Close(streamPtr, rpc_SpriteID, procID, 0, 0,
- (ClientData)NIL);
- }
- Fsutil_WaitListDelete(&ctrlHandlePtr->readWaitList);
- Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlClientKill --
- *
- * See if a crashed client was running a pseudo-device master.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Clears the serverID field if it matches the crashed host's ID.
- * This unlocks the handle before returning.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- void
- FspdevControlClientKill(hdrPtr, clientID)
- Fs_HandleHeader *hdrPtr; /* File being killed */
- int clientID; /* Client ID to kill. */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr =
- (Fspdev_ControlIOHandle *)hdrPtr;
-
- if (ctrlHandlePtr->serverID == clientID) {
- ctrlHandlePtr->serverID = NIL;
- Fsutil_RecoverySyncLockCleanup(&ctrlHandlePtr->rmt.recovery);
- Fsutil_HandleRemove(ctrlHandlePtr);
- fs_Stats.object.controls--;
- } else {
- Fsutil_HandleUnlock(ctrlHandlePtr);
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * FspdevControlScavenge --
- *
- * See if this control stream handle is still needed.
- *
- * Results:
- * TRUE if the handle was removed.
- *
- * Side effects:
- * Will remove the handle if there is no server.
- *
- *----------------------------------------------------------------------
- */
- Boolean
- FspdevControlScavenge(hdrPtr)
- Fs_HandleHeader *hdrPtr; /* File being encapsulated */
- {
- register Fspdev_ControlIOHandle *ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
-
- if (ctrlHandlePtr->serverID == NIL) {
- Fsutil_RecoverySyncLockCleanup(&ctrlHandlePtr->rmt.recovery);
- Fsutil_HandleRemove(ctrlHandlePtr);
- fs_Stats.object.controls--;
- return(TRUE);
- } else {
- Fsutil_HandleUnlock(ctrlHandlePtr);
- return(FALSE);
- }
- }
-